//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#include <core.h>
#include <init.h>
#include "recycle.h"

STATIC DECL_CODEINIT bool_t RecycleInitSections(
        /* [in, out] */ size_t *puNumberOfRecycledPages);

#if defined(_RELEASE) && defined(_GNUC)
STATIC DECL_CODEINIT bool_t RecycleImageHead(
        /* [in, out] */ size_t *puNumberOfRecycledPages);
#endif // _RELEASE && _GNUC

EXTERN DECL_CODEINIT bool_t RecycleAll()
{
#ifndef _mips

    // TODO(mips): The first page is the exception code,
    // It's can't be distribute and alter.

    // Recycle init stack
    if (!ReclaimPages(bsp.regionOfInitStack.uBasePageNo,
        bsp.regionOfInitStack.uLimitPageNo)) {
        return FALSE;
    }
#endif

    size_t uNumberOfRecycledPages = 0;
    // TODO(mips): because the evc linker
#ifndef _EVC
    if (!RecycleInitSections(&uNumberOfRecycledPages)) {
        return FALSE;
    }
#endif

#if defined(_RELEASE) && defined(_GNUC) && !defined(_mips)
    if (!RecycleImageHead(&uNumberOfRecycledPages)) {
        return FALSE;
    }
#endif // _RELEASE && _GNUC && !_mips

    kprintf("%u Pages recycled.\n", uNumberOfRecycledPages);
    return TRUE;
}

DECL_LINKERSYMBOL int _RecycleBegin;
DECL_LINKERSYMBOL int _RecycleEnd;

STATIC DECL_CODEINIT bool_t RecycleInitSections(
    /* [in, out] */ size_t *puNumberOfRecycledPages)
{
    assert(IsAlignment2(&_RecycleBegin, PAGE_SIZE));
    assert(IsAlignment2(&_RecycleEnd,   PAGE_SIZE));

    uint_t uBasePageNo  = VIRTADDR_TO_PAGENO(&_RecycleBegin);
    uint_t uLimitPageNo = VIRTADDR_TO_PAGENO(&_RecycleEnd);

    *puNumberOfRecycledPages += uLimitPageNo - uBasePageNo;

    return ReclaimPages(uBasePageNo, uLimitPageNo);
}

#if defined(_RELEASE) && defined(_GNUC)

DECL_LINKERSYMBOL int _HeaderBegin;
DECL_LINKERSYMBOL int _HeaderEnd;

STATIC DECL_CODEINIT bool_t RecycleImageHead(
    /* [in, out] */ size_t *puNumberOfRecycledPages)
{
    assert(IsAlignment2(&_HeaderBegin, PAGE_SIZE));
    assert(IsAlignment2(&_HeaderEnd,   PAGE_SIZE));

    uint_t uBasePageNo  = VIRTADDR_TO_PAGENO(&_HeaderBegin);
    uint_t uLimitPageNo = VIRTADDR_TO_PAGENO(&_HeaderEnd);

    *puNumberOfRecycledPages += uLimitPageNo - uBasePageNo;

    return ReclaimPages(uBasePageNo, uLimitPageNo);
}

#endif // _RELEASE && _GNUC
